package com.springboot.middleware.middleware_redisson.server.service;

import com.springboot.middleware.middleware_redisson.model.entity.UserReg;
import com.springboot.middleware.middleware_redisson.model.mapper.UserRegMapper;
import com.springboot.middleware.middleware_redisson.server.dto.UserRegDto;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
public class UserRegServiceRedissonImpl implements UserRegService {
    private static final Logger log = LoggerFactory.getLogger(UserRegServiceRedissonImpl.class);

    @Autowired
    private RedissonClient redissonClient;
    @Autowired
    private UserRegMapper userRegMapper;

    /**
     * 处理用户提交注册的请求 - 加Redisson分布式锁
     *
     * @param dto (userName, password)
     * @throws Exception 用户信息已经存在 or 获取分布式锁失败
     */
    @Override
    public void userRegRedisson(UserRegDto dto) throws Exception {
        // 定义锁的名称
        final String lockName = "redissonOneLock" + dto.getUserName();
        // 获取分布式锁实例
        RLock lock = redissonClient.getLock(lockName);
        try {
            lock.lock(10, TimeUnit.SECONDS);
            UserReg userReg = userRegMapper.selectByUserName(dto.getUserName());
            if (userReg == null) {
                UserReg entry = new UserReg();
                entry.setUserName(dto.getUserName());
                entry.setPassword(dto.getPassword());
                entry.setCreateTime(new Date());
                userRegMapper.insertSelective(entry);
                log.info("---获取Redisson一次性锁--, 当前用户名为:{}", dto.getUserName());
            } else {
                throw new Exception("当前用户已经存在");
            }
        } catch (Exception e) {
            log.error("--- 获取Redisson分布式锁失败! ---");
            throw e;
        } finally {
            //无论什么情况, 最后都应该释放该资源
            lock.unlock();
        }
    }
}
